// Author : Zhuowen Tu


#include "mcmcRegionImage.h"
#include "mcLinkList.h"


// construction & destruction
MCMC_Region_Image::MCMC_Region_Image()
{
	width	= 0;
	height	= 0;
	pmx_data = NULL;
	count	= 0;
}

MCMC_Region_Image::~MCMC_Region_Image()
{
	Free();
}

void MCMC_Region_Image::Free(void)
{
	if (pmx_data != NULL)
		delete []pmx_data;
	pmx_data = NULL;
	count = 0;
}

void MCMC_Region_Image::Init(const int num_region)
{
	Free();
	count = num_region;
	if (count>0)
		pmx_data = new mcmcMatrix<int>[count];
}

void MCMC_Region_Image::Extract(Raster<int> &image, const int num_region)
{
	int				i,j,num,k;
	mcmcMatrix<int>	mx_pixels;

	width	= image.cols();
	height	= image.rows();

	// determin how many regions there are
	count = num_region;
	if (count<=0)
		count = image.GetMax();
	if (count<=0)
		return;

	// for each region how many pixels
	mx_pixels.SetDimension(count,1);
	mx_pixels.InitValue(0);
	for (j=0; j<image.rows(); j++)
		for (i=0; i<image.cols(); i++)
		{
			if (image.Data(j,i)<=count && image.Data(j,i)>0)
				mx_pixels(image.Data(j,i)-1)++;
		}

	// allocate memory
	Init(count);
	for (i=0; i<count; i++)
		pmx_data[i].SetDimension(mx_pixels(i),2);

	mx_pixels.InitValue(0);
	for (j=0; j<image.rows(); j++)
		for (i=0; i<image.cols(); i++)
		{
			if (image.Data(j,i)<=count && image.Data(j,i)>0)
			{
				k = image.Data(j,i)-1;
				num = mx_pixels(k);
				X(k,num) = i;
				Y(k,num) = j;
				mx_pixels(k)++;
			}
		}
}

int	MCMC_Region_Image::GetPixelNum(const int mx)
{
	assert(mx<count);
	return pmx_data[mx].rows();
}

int& MCMC_Region_Image::X(const int mx, const int i)
{
	int j;

	assert(mx<count);
	j = (i+pmx_data[mx].rows())%pmx_data[mx].rows();
	return pmx_data[mx](j,0);
}

int& MCMC_Region_Image::Y(const int mx, const int i)
{
	int j;

	assert(mx<count);
	j = (i+pmx_data[mx].rows())%pmx_data[mx].rows();
	return pmx_data[mx](j,1);
}

void MCMC_Region_Image::ExtractExtn(Raster<int> &image)
{
	mcmcMatrix<int>	union1,union2;
	int				num;
	int			i,j,m,n,k;
	mcmcMatrix<int>		mx_index,mx_pixel;
	LinkList<McImagePoint> list_rep;
	McImagePoint	pt;
	bool			bGo;

	width	= image.cols();
	height	= image.rows();

	mx_index.SetDimension(image.rows(),image.cols());
	mx_index.InitValue(0);

	// find connected regions
	image.FindUnion(union1, union2);
	for (j=0; j<union1.rows(); j++)
		for (i=0; i<union1.cols(); i++)
		{
			if (image(j,i)>0)
			{
				image.GetRepresentative(union1,j,i,m,n);
				if (mx_index(m,n)==0)
				{
					pt.SetY(m);
					pt.SetX(n);
					list_rep.Insert(pt);
				}
				mx_index(m,n)++;
			}
		}

	count = list_rep.Num();
	if (count<=0)
		return;
	// allocate memory
	Init(count);
	mx_pixel.SetDimension(count,1);
	mx_pixel.InitValue(0);
	bGo = list_rep.GetFirst(pt);
	i = 0;
	while (bGo)
	{
		pmx_data[i].SetDimension(mx_index(pt.Y(),pt.X()),2);
		assert (mx_index(pt.Y(),pt.X())>0);

		mx_index(pt.Y(),pt.X()) = i;
		bGo = list_rep.GetNext(pt);
		i++;
	}
	mx_pixel.InitValue(0);
	for (j=0; j<image.rows(); j++)
		for (i=0; i<image.cols(); i++)
		{
			if (image(j,i)>0)
			{
				image.GetRepresentative(union1,j,i,m,n);
				k = mx_index(m,n);
				num = mx_pixel(k);
				X(k,num) = i;
				Y(k,num) = j;
				mx_pixel(k)++;
			}
		}
}


/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
void MCMC_Edge_Image::SetLength(const int mx, const int len)
{
	assert(mx<count);

	pmx_data[mx].SetDimension(len,2);
}
